package logic

import (
	"bluebell/dao/mysql"
	"bluebell/dao/redis"
	"bluebell/models"
	"bluebell/pkg/snowflake"
	"strconv"

	"go.uber.org/zap"
)

func CreatePost(p *models.Post) (err error) {
	// 生成post_id
	p.ID = snowflake.GenID()
	// 保存到数据库
	err = mysql.CreatePost(p)
	if err != nil {
		return
	}
	err = redis.CreatePost(p.ID, p.CommunityID)
	return
}

func GetPostByID(id int64) (p *models.ApiPostDetail, err error) {
	// 从数据库获取post
	post, err := mysql.GetPostByID(id)
	if err != nil {
		zap.L().Error("mysql.GetPostByID(id) failed", zap.Error(err))
		return
	}
	// 根据作者id查询作者信息
	author, err := mysql.GetUserById(post.AuthorID)
	if err != nil {
		zap.L().Error("mysql.GetUserByID(post.AuthorID) failed", zap.Error(err))
		return
	}
	// 根据社区id查询社区信息
	community, err := mysql.GetCommunityDetailByID(post.CommunityID)
	if err != nil {
		zap.L().Error("mysql.GetCommunityDetailByID(post.CommunityID) failed", zap.Error(err))
		return
	}
	// 组装返回结果
	p = &models.ApiPostDetail{
		AuthorName:      author.Username,
		Post:            post,
		CommunityDetail: community,
	}
	return
}

func GetPostList(page, size int64) (pl []*models.ApiPostDetail, err error) {
	posts, err := mysql.GetPostList(page, size)

	if err != nil {
		return nil, err
	}
	pl = make([]*models.ApiPostDetail, 0, len(posts))
	for _, post := range posts {
		// 根据作者id查询作者信息
		author, err := mysql.GetUserById(post.AuthorID)
		if err != nil {
			zap.L().Error("mysql.GetUserByID() failed", zap.Error(err))
			continue
		}
		// 根据社区id查询社区信息
		community, err := mysql.GetCommunityDetailByID(post.CommunityID)
		if err != nil {
			zap.L().Error("mysql.GetCommunityDetailByID() failed", zap.Error(err))
			continue
		}
		// 组装返回结果
		pl = append(pl, &models.ApiPostDetail{
			AuthorName:      author.Username,
			Post:            post,
			CommunityDetail: community,
		})
	}
	return
}

func PostVote(userID int64, p *models.ParamVoteData) error {
	zap.L().Debug("PostVote",
		zap.Int64("userID", userID),
		zap.String("postID", p.PostID),
		zap.Int8("direction", p.Direction))
	return redis.PostVote(strconv.Itoa(int(userID)), p.PostID, float64(p.Direction))
}

func GetPostList2(p *models.ParamPostList) (pl []*models.ApiPostDetail, err error) {
	// 从redis中获取id列表
	ids, err := redis.GetPostIDsInOrder(p)
	if err != nil {
		return nil, err
	}
	if len(ids) == 0 {
		zap.L().Warn("GetPostList2: no post found")
		return nil, nil
	}
	zap.L().Debug("GetPostList2", zap.Any("ids", ids))
	// 根据id从mysql中获取详情
	posts, err := mysql.GetPostListByIDs(ids)

	if err != nil {
		return
	}
	zap.L().Debug("GetPostList2", zap.Any("posts", posts))

	// 提前查询好每篇帖子的投票数
	vateData, err := redis.GetPostVoteData(ids)

	for idx, post := range posts {
		// 根据作者id查询作者信息
		author, err := mysql.GetUserById(post.AuthorID)
		if err != nil {
			zap.L().Error("mysql.GetUserByID() failed", zap.Error(err))
			continue
		}
		// 根据社区id查询社区信息
		community, err := mysql.GetCommunityDetailByID(post.CommunityID)
		if err != nil {
			zap.L().Error("mysql.GetCommunityDetailByID() failed", zap.Error(err))
			continue
		}
		// 组装返回结果
		pl = append(pl, &models.ApiPostDetail{
			AuthorName:      author.Username,
			VoteNum:         vateData[idx],
			Post:            post,
			CommunityDetail: community,
		})
	}
	return
}
